package cn.edu.hznu.util.exception;

import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;

public class ExceptionUtil {
	
	@FunctionalInterface
	public interface ConsumerWithExceptions<T> {
		void accet(T t) throws Exception;
	}
	
	@FunctionalInterface 
	public interface FunctionWithExceptions<T, R> {
		R apply(T t) throws Exception;
	}
	
	@FunctionalInterface
	public interface SupplierWithExceptions<T> {
		T get() throws Exception;
	}
	
	@FunctionalInterface
	public interface RunableWithExceptions {
		void accpt() throws Exception;
	}
	
	/*
	 * forEach(rethrowConsumer(name -> sysout(Class.forName(name))));
	 */
	public static <T> Consumer<T> rethrowConsumer(ConsumerWithExceptions<T> consumer) {
		return t -> {
			try {
				consumer.accet(t);
			} catch (Exception e) {
				throwAsUnchecked(e);
			}
		};
	}
	
	/*
	 * .map(rethrowFunction(name -> Class::forName));
	 */
	public static <T, R> Function<T, R> rethrowFunction(FunctionWithExceptions<T, R> function) {
		return t -> {
			try {
				return function.apply(t);
			} catch (Exception e) {
				throwAsUnchecked(e);
				return null; 
			}
		};
	}
	
	/*
	 * rethrowSupplier(() -> new XXX())
	 */
	public static <T> Supplier<T> rethrowSupplier(SupplierWithExceptions<T> supplier) {
		return () -> {
			try {
				return supplier.get();
			} catch (Exception e) {
				throwAsUnchecked(e);
				return null;
			}
		};
	}
	
	/*
	 * uncheck(() -> Class::forName(name))
	 */
	public static void uncheck(RunableWithExceptions t) {
		try {
			t.accpt();
		} catch (Exception e) {
			throwAsUnchecked(e);
		}
	}
	
	/*
	 * 
	 */
	public static <R> R uncheck (SupplierWithExceptions<R> supplier) {
		try {
			return supplier.get();
		} catch (Exception e) {
			throwAsUnchecked(e);
			return null;
		}
	}
	
	public static <T, R> R uncheck (FunctionWithExceptions<T, R> function, T t) {
		try {
			return function.apply(t);
		} catch (Exception e) {
			throwAsUnchecked(e);
			return null;
		}
	}

	private static <E extends Throwable> void throwAsUnchecked(Exception e) throws E{
		throw (E) e;
	}
	

}
